home *** CD-ROM | disk | FTP | other *** search
- unit Main;
-
- interface
-
- uses
- Windows, ComObj, ActiveX, SteveAddIn_TLB, AddInDesignerObjects_TLB, Office_TLB,
- EventSink;
-
- type
- TOfficeHostApp = (ohaExcel, ohaWord, ohaOutlook, ohaPowerPoint, ohaAccess);
- TOfficeHostApps = set of TOfficeHostApp;
-
- TSteveAddIn = class(TAutoObject, ISteveAddIn, IDTExtensibility2)
- private
- FApplication: OleVariant;
- FButton: CommandBarButton;
- FCommandBar: CommandBar;
- FCookie: Longint;
- FEventSink: TEventSink;
- FHostApp: TOfficeHostApp;
- protected
- { IDTExtensibility2 methods }
- procedure OnConnection(const Application_: IDispatch;
- ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
- var custom: PSafeArray); safecall;
- procedure OnDisconnection(RemoveMode: ext_DisconnectMode;
- var custom: PSafeArray); safecall;
- procedure OnAddInsUpdate(var custom: PSafeArray); safecall;
- procedure OnStartupComplete(var custom: PSafeArray); safecall;
- procedure OnBeginShutdown(var custom: PSafeArray); safecall;
- public
- procedure CommandBarButtonClick(const Ctrl: CommandBarButton;
- var CancelDefault: WordBool);
- property Application: OleVariant read FApplication;
- property HostApp: TOfficeHostApp read FHostApp;
- end;
-
- TOfficeAddInFactory = class(TAutoObjectFactory)
- private
- FFriendlyName: string;
- FLoadBehavior: Integer;
- FSupportedApps: TOfficeHostApps;
- procedure ReallyDeleteRegKey(const KeyName: string);
- protected
- procedure RegisterAddIn(const KeyName: string); virtual;
- public
- constructor Create(ComServer: TComServerObject; AutoClass: TAutoClass;
- const ClassID: TGUID; Instancing: TClassInstancing;
- ThreadingModel: TThreadingModel; SupportedApps: TOfficeHostApps;
- const FriendlyName: string; LoadBehavior: Integer);
- procedure UpdateRegistry(Register: Boolean); override;
- end;
-
- implementation
-
- uses SysUtils, ComServ, Excel_TLB, Word_TLB, Dialogs, CmdBarHack, Registry,
- Classes;
-
- { TSteveAddIn }
-
- // CommandBarButtonClick is the click handler for our command bar button
- procedure TSteveAddIn.CommandBarButtonClick(const Ctrl: CommandBarButton;
- var CancelDefault: WordBool);
- begin
- // Let the user know that the button was clicked. In real life, you'd do
- // something more userful in here.
- ShowMessage('You clicked on the button!');
- end;
-
- // OnAddInsUpdate is called to notify the add-in that the Office host
- // application's COMAddIns collection has changed.
- procedure TSteveAddIn.OnAddInsUpdate(var custom: PSafeArray);
- begin
- // nothing to do here
- end;
-
- // OnBeginShutdown is called immediately prior to the Office host application
- // going into its shutdown routine.
- procedure TSteveAddIn.OnBeginShutdown(var custom: PSafeArray);
- begin
- // Unhook event sink
- InterfaceDisconnect(FButton, DIID__CommandBarButtonEvents, FCookie);
- // Kill Button and CommandBar
- FButton.Delete(False);
- FCommandBar.Delete;
- end;
-
- // OnConnection is called when the add-in is loaded by the Office host
- // application. The add-in can be loaded under any one of several circumstances,
- // as indicated by the value of the ConnectMode parameter:
- //
- // ext_cm_AfterStartup: add-in was loaded after startup (by the end user)
- // ext_cm_Startup: add-in was loaded during startup (normal mode)
- // ext_cm_External: add-in was loaded from an external source (like a
- // VBA macro or another component)
- // ext_cm_CommandLine: add-in whas loaded from the command line
- //
- // The Application_ parameter contains an IDispatch for the "application"
- // interface of the Office host application. The AddInInst contains an
- // IDispatch representing this add-in in the Office host application's COMAddIns
- // collection.
- procedure TSteveAddIn.OnConnection(const Application_: IDispatch;
- ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
- var custom: PSafeArray);
- var
- Unk: IUnknown;
- begin
- // QueryInterface for the "application" interface of the Office host
- // applications that we support. When we find one, we know who is our host.
- if Application_.QueryInterface(Word_TLB._Application, Unk) = S_OK then
- FHostApp := ohaWord
- else if Application_.QueryInterface(Excel_TLB._Application, Unk) = S_OK then
- FHostApp := ohaExcel
- else begin
- MessageDlg('This Add-in only supports Word and Excel.', mtError,
- [mbOk], 0);
- raise SysUtils.Exception.Create('Initialization failed');
- end;
- FApplication := Application_;
- // If we are connecting during startup, then OnStartupComplete will be called
- // by the Office host application, and we should perform our initialization
- // there. Otherwise, we'll assume Office is already initialized and call
- // OnStartupComplete ourselves.
- if (ConnectMode <> ext_cm_Startup) then OnStartupComplete(custom);
- end;
-
- // OnDisconnection is called when the add-in is unloaded by the Office
- // host application. This occurs wither when the user manually unloads the
- // add-in (RemoveMode = ext_dm_UserClosed) or the Office host application shuts
- // down (RemoveMode = ext_dm_HostShutdown).
- procedure TSteveAddIn.OnDisconnection(RemoveMode: ext_DisconnectMode;
- var custom: PSafeArray);
- begin
- // If we are not unloading as a result of the host shutting down,
- // OnBeginShutdown won't be called by the Office host application, so we call
- // it manually in order to clean up toolbar.
- if (RemoveMode <> ext_dm_HostShutdown) then OnBeginShutdown(custom);
- FEventSink.Free;
- // Release all references
- FButton := nil;
- FCommandBar := nil;
- FApplication := Unassigned;
- end;
-
- // OnStartupComplete is called after the Office host application has completed
- // its startup rigmarole, including loading of any necessary files, add-ins, or
- // other objects into memory. This method is not called for add-ins that are
- // loaded by the user or by VBA code, however we are calling it from
- // OnConnection to ensure the code in this method is always called.
- procedure TSteveAddIn.OnStartupComplete(var custom: PSafeArray);
- var
- CmdBars: CommandBars;
- Control: CommandBarControl;
- I: Integer;
- begin
- CmdBars := CommandBars(GetAppCommandBars(FApplication));
- // Need to iterate over CommandBars to see if we are already installed.
- // If not, create a new one.
- for I := 1 to CmdBars.Count do
- if CmdBars.Item[I].Name = 'StevesCommandBar' then
- FCommandBar := CmdBars.Item[I];
- if FCommandBar = nil then
- FCommandBar := CmdBars.Add('StevesCommandBar', EmptyParam, EmptyParam, EmptyParam);
- // If CommandBar already has a control on it, then assume it's our button,
- // otherwise add a new one.
- if FCommandBar.Controls_.Count > 0 then
- Control := FCommandBar.COntrols_.Item[1]
- else
- Control := FCommandBar.Controls_.Add(msoControlButton, EmptyParam,
- EmptyParam, EmptyParam, EmptyParam);
- FButton := CommandBarButton(Control);
- FButton.Caption := 'Steve''s Add-in';
- FButton.Style := msoButtonCaption;
- FButton.Visible := True;
- // hook up Click event
- FEventSink := TEventSink.Create(CommandBarButtonClick);
- InterfaceConnect(FButton, DIID__CommandBarButtonEvents, FEventSink, FCookie);
- FCommandBar.Visible := True;
- end;
-
- { TOfficeAddInFactory }
-
- constructor TOfficeAddInFactory.Create(ComServer: TComServerObject;
- AutoClass: TAutoClass; const ClassID: TGUID;
- Instancing: TClassInstancing; ThreadingModel: TThreadingModel;
- SupportedApps: TOfficeHostApps; const FriendlyName: string;
- LoadBehavior: Integer);
- begin
- inherited Create(ComServer, AutoClass, ClassID, Instancing, ThreadingModel);
- FSupportedApps := SupportedApps;
- FFriendlyName := FriendlyName;
- FLoadBehavior := LoadBehavior;
- end;
-
- procedure TOfficeAddInFactory.ReallyDeleteRegKey(const KeyName: string);
- var
- R: TRegistry;
- Values: TStringList;
- I: Integer;
- begin
- // Deletes a reg key, including underlying values
- Values := TStringList.Create;
- R := TRegistry.Create;
- try
- if R.OpenKey(KeyName, False) then
- begin
- R.GetValueNames(Values);
- for I := 0 to Values.Count - 1 do
- R.DeleteValue(Values[I]);
- R.CloseKey;
- R.DeleteKey(KeyName);
- end;
- finally
- R.Free;
- Values.Free;
- end;
- end;
-
- procedure TOfficeAddInFactory.RegisterAddIn(const KeyName: string);
- var
- R: TRegistry;
- begin
- R := TRegistry.Create;
- try
- // Makes necessary registry entries to register this COM server as an add-in
- if not R.OpenKey(KeyName, True) then raise Exception.Create('');
- R.WriteString('FriendlyName', FFriendlyName);
- R.WriteString('Description', Description);
- R.WriteInteger('LoadBehavior', FLoadBehavior);
- R.WriteInteger('CommandLineSafe', 0);
- finally
- R.Free;
- end;
- end;
-
- procedure TOfficeAddInFactory.UpdateRegistry(Register: Boolean);
- const
- AppNames: array[TOfficeHostApp] of string[15] = ('Excel', 'Word', 'Outlook',
- 'PowerPoint', 'Access');
- AddInKey = '\Software\Microsoft\Office\%s\AddIns\%s';
- var
- I: TOfficeHostApp;
- CurrentAddInKey: string;
- begin
- inherited UpdateRegistry(Register);
- // iterate over all supported apps and update registry
- for I := Low(TOfficeHostApp) to High(TOfficeHostApp) do
- if I in FSupportedApps then
- begin
- CurrentAddInKey := Format(AddInKey, [AppNames[I], ProgID]);
- if Register then RegisterAddIn(CurrentAddInKey)
- else ReallyDeleteRegKey(CurrentAddInKey);
- end;
- end;
-
- initialization
- TOfficeAddInFactory.Create(ComServer, TSteveAddIn, Class_SteveAddIn_,
- ciMultiInstance, tmApartment, [ohaExcel, ohaWord], 'Steve''s Add-in', 3);
- end.
-